package cn.sczhyt.modules.szhy.controller;

import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import cn.sczhyt.common.utils.ApplicationContextRegister;
import cn.sczhyt.common.utils.R;
import cn.sczhyt.modules.szhy.entity.MeetingEntity;
import cn.sczhyt.modules.szhy.entity.MeetingTopicsEntity;
import cn.sczhyt.modules.szhy.entity.MeetingVoteEntity;
import cn.sczhyt.modules.szhy.service.MeetingService;
import cn.sczhyt.modules.szhy.service.MeetingTopicsService;
import cn.sczhyt.modules.szhy.service.MeetingVoteService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.sf.json.JSONObject;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

/**
 * @author zhengkai.blog.csdn.net
 */
@ServerEndpoint("/imserver/{userId}")
@Component
public class WebSocketController {

    static Log log = LogFactory.get(WebSocketController.class);
    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;
    /**
     * concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
     */
    private static CopyOnWriteArraySet<WebSocketController> webSocketSet = new CopyOnWriteArraySet<WebSocketController>();
    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    /**
     * 接收userId
     */
    private String userId = "";
    /**
     * 调用service的工具类
     */
    private ApplicationContext act = ApplicationContextRegister.getApplicationContext();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        this.session = session;
        this.userId = userId;
        webSocketSet.add(this);
        addOnlineCount();           //在线数加1
        log.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());

        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("用户:" + userId + ",网络异常!!!!!!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1

        log.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("用户消息:" + userId + ",报文:" + message);
        System.out.println("用户发送的消息内容："+message);
        JSONObject jsonObject = JSONObject.fromObject(message);
        //判断投票状态  YES
        if (jsonObject.has("ifTopics") && jsonObject.has("meetingId") && jsonObject.has("topicsId")) {
            Integer ifTopics = Integer.valueOf(jsonObject.get("ifTopics").toString());
            String topicsId = jsonObject.get("topicsId").toString();
            String meetingId = jsonObject.get("meetingId").toString();
            //是否开始投票  YES
            switch (ifTopics) {
                case 1:
                    this.updateTopics(topicsId, 1);
                    for (WebSocketController item : webSocketSet) {
                        if (!item.userId.equals(userId)) {
                            try {
                                JSONObject object = new JSONObject();
                                object.put("meetingId", meetingId);
                                object.put("topicsId", topicsId);
                                String topicsName = this.getMeetingTopicsEntity(topicsId).getTopicsName();
                                object.put("topicsName", topicsName);
                                object.put("ifTopics", ifTopics);
                                System.out.println("返回的数据:" + object.toString());
                                item.sendMessage(object.toString());
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    //告知管理员投票开始
                    try {
                        this.sendMessage(R.ok().put("ifTopics",ifTopics).toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                case 2:
                    //TODO  结束投票的功能实现
                    //结束投票改变议题状态   不允许再投票
                    this.updateTopics(topicsId, 2);


                    for (WebSocketController item : webSocketSet) {

                        //告知管理员投票已结束
                        try {

                            JSONObject object = new JSONObject();
                            object.put("meetingId", meetingId);
                            object.put("topicsId", topicsId);
                            String topicsName = this.getMeetingTopicsEntity(topicsId).getTopicsName();
                            object.put("topicsName", topicsName);
                            object.put("ifTopics", ifTopics);
                            System.out.println("返回的数据:" + object.toString());
                        if (item.userId.equals(userId)){
                                this.sendMessage(R.ok().put("ifTopics",ifTopics).toString());
                            }
                            item.sendMessage(object.toString());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }

                    break;
                //重新投票
                case 3:
                    //删除已投票记录
                    this.deleteMeetingVote(topicsId,meetingId);
                    //在进行投票
                    this.updateTopics(topicsId, 1);
                    //群发投票基本信息给用户做投票准备
                    for (WebSocketController item : webSocketSet) {
                        if (!item.userId.equals(userId)) {
                            try {
                                JSONObject object = new JSONObject();
                                object.put("meetingId", meetingId);
                                object.put("topicsId", topicsId);
                                String topicsName = this.getMeetingTopicsEntity(topicsId).getTopicsName();
                                object.put("topicsName", topicsName);
                                object.put("ifTopics", ifTopics);
                                System.out.println("返回的数据:" + object.toString());
                                item.sendMessage(object.toString());
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    //告知管理员投票开始
                    try {
                        this.sendMessage(R.ok().put("ifTopics",ifTopics).toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                    //查看结果
                case 4:


                    //推送表决结果给所有用户
                    for (WebSocketController item : webSocketSet) {
                        //if (!item.userId.equals(userId)) {
                        try {
                            JSONObject object = this.voteCount(topicsId,meetingId);
                            String meetingName = this.findMeetingName(meetingId);

                            MeetingTopicsEntity meetingTopicsEntity = this.getMeetingTopicsEntity(topicsId);
                            String topicsName = meetingTopicsEntity.getTopicsName();
                            Integer ifAnonymous = meetingTopicsEntity.getIfAnonymous();
                            object.put("ifAnonymous",ifAnonymous);
                            object.put("topicsName", topicsName);
                            object.put("meetingName",meetingName);
                            object.put("ifTopics", ifTopics);
                            System.out.println("返回的数据:" + object.toString());
                            item.sendMessage(object.toString());
                        } catch (IOException e) {
                            e.printStackTrace();
                            //     }
                        }
                    }
                    //告知推送表决结果成功
                    try {
                        this.sendMessage(R.ok().put("ifTopics",ifTopics).toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                default:
                    //告知管理员投票开始
                    try {
                        this.sendMessage(R.error(201,"参数错误").toString());
                        this.sendMessage(R.ok().toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }


        }



    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 修改议题状态
     */

    private void updateTopics(String topicsId, Integer ifTopics) {

        MeetingTopicsService meetingTopicsService = act.getBean(MeetingTopicsService.class);
        meetingTopicsService.updateByTopics(topicsId,ifTopics);
    }

    /**
     * 删除投票记录
     */

    private void deleteMeetingVote(String topicsId,String meetingId){
        MeetingVoteService meetingVoteService = act.getBean(MeetingVoteService.class);
        meetingVoteService.remove(new QueryWrapper<MeetingVoteEntity>()
                .eq("topics_id",topicsId)
                .eq("meeting_id",meetingId));
    }

    /**
     * 获取表决结果
     * @param topicsId
     * @param meetingId
     * @return
     */
    private JSONObject voteCount(String topicsId,String meetingId){
        MeetingVoteService meetingVoteService = act.getBean(MeetingVoteService.class);

        JSONObject jsonObject = meetingVoteService.voteCount(meetingId, topicsId);
        return jsonObject;
    }

    /**
     * 获取议题
     * @param topicsId
     * @return
     */
    private MeetingTopicsEntity getMeetingTopicsEntity(String topicsId) {
        MeetingTopicsService meetingTopicsService = act.getBean(MeetingTopicsService.class);
        MeetingTopicsEntity meetingTopicsEntity = meetingTopicsService.getById(topicsId);
        return meetingTopicsEntity;
    }
    /**
     * 获取会议名称
     * @param meetingId
     * @return
     */
    private String findMeetingName(String meetingId) {
        MeetingService meetingService = act.getBean(MeetingService.class);
        MeetingEntity meetingEntity = meetingService.getById(meetingId);
        return meetingEntity.getMeetingName();
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketController.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketController.onlineCount--;
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


}
